﻿using System;
using System.Windows;
using ZOIL.DataModel;

namespace ZOIL.Library.Behaviors
{
    public delegate void SelectionEventHandler(object sender, SelectionEventArgs e);

    public class SelectionBehavior : RuntimeBehavior<ZLandscapeCanvas, PluginSelectionBehavior>
    {
        #region dependeny properties

        #region SelectionMode

        /// <summary>
        /// SelectionMode Dependency Property
        /// </summary>
        public static readonly DependencyProperty SelectionModeProperty = DependencyProperty.Register("SelectionMode", typeof(SelectionModes), typeof(SelectionBehavior), new FrameworkPropertyMetadata(SelectionModes.BoundingBox, OnSelectionModeChanged));

        /// <summary>
        /// Gets or sets the SelectionMode property. This dependency property 
        /// indicates ....
        /// </summary>
        public SelectionModes SelectionMode
        {
            get { return (SelectionModes)GetValue(SelectionModeProperty); }
            set { SetValue(SelectionModeProperty, value); }
        }

        /// <summary>
        /// Handles changes to the SelectionMode property.
        /// </summary>
        private static void OnSelectionModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var target = (SelectionBehavior)d;
            var oldSelectionMode = (SelectionModes)e.OldValue;
            var newSelectionMode = target.SelectionMode;
            target.OnSelectionModeChanged(oldSelectionMode, newSelectionMode);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the SelectionMode property.
        /// </summary>
        protected virtual void OnSelectionModeChanged(SelectionModes oldSelectionMode, SelectionModes newSelectionMode)
        {
        }

        #endregion

        #region TargetType

        /// <summary>
        /// TargetType Dependency Property
        /// </summary>
        public static readonly DependencyProperty TargetTypeProperty = DependencyProperty.Register("TargetType", typeof(Type), typeof(SelectionBehavior), new FrameworkPropertyMetadata(typeof(DependencyObject), OnTargetTypeChanged));

        /// <summary>
        /// Gets or sets the TargetType property. This dependency property 
        /// indicates ....
        /// </summary>
        public Type TargetType
        {
            get { return (Type)GetValue(TargetTypeProperty); }
            set { SetValue(TargetTypeProperty, value); }
        }

        /// <summary>
        /// Handles changes to the TargetType property.
        /// </summary>
        private static void OnTargetTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var target = (SelectionBehavior)d;
            var oldTargetType = (Type)e.OldValue;
            var newTargetType = target.TargetType;
            target.OnTargetTypeChanged(oldTargetType, newTargetType);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the TargetType property.
        /// </summary>
        protected virtual void OnTargetTypeChanged(Type oldTargetType, Type newTargetType)
        {
        }

        #endregion

        #endregion

        #region Routed Events

        #region Selection Finished

        public static readonly RoutedEvent SelectionFinishedEvent = EventManager.RegisterRoutedEvent("SelectionFinished", RoutingStrategy.Bubble, typeof(SelectionEventHandler), typeof(SelectionBehavior));

        public event SelectionEventHandler SelectionFinished
        {
            add { AddRoutedEventHandler(SelectionFinishedEvent, value); }
            remove { RemoveRoutedEventHandler(SelectionFinishedEvent, value); }
        }

        #endregion

        #region Selection Started

        public static readonly RoutedEvent SelectionStartedEvent = EventManager.RegisterRoutedEvent("SelectionStarted", RoutingStrategy.Bubble, typeof(SelectionEventHandler), typeof(SelectionBehavior));

        public event SelectionEventHandler SelectionStarted
        {
            add { AddRoutedEventHandler(SelectionStartedEvent, value); }
            remove { RemoveRoutedEventHandler(SelectionStartedEvent, value); }
        }

        #endregion

        #region Selection Changed

        public static readonly RoutedEvent SelectionChangedEvent = EventManager.RegisterRoutedEvent("SelectionChanged", RoutingStrategy.Bubble, typeof(SelectionEventHandler), typeof(SelectionBehavior));

        public event SelectionEventHandler SelectionChanged
        {
            add { AddRoutedEventHandler(SelectionChangedEvent, value); }
            remove { RemoveRoutedEventHandler(SelectionChangedEvent, value); }
        }

        #endregion

        #region Selection Cancelled

        public static readonly RoutedEvent SelectionCancelledEvent = EventManager.RegisterRoutedEvent("SelectionCancelled", RoutingStrategy.Bubble, typeof(SelectionEventHandler), typeof(SelectionBehavior));

        public event SelectionEventHandler SelectionCancelled
        {
            add { AddRoutedEventHandler(SelectionCancelledEvent, value); }
            remove { RemoveRoutedEventHandler(SelectionCancelledEvent, value); }
        }

        #endregion

        #endregion

        #region event helper

        internal void RaiseSelectionStartedEvent(Selection selection)
        {
            var args = new SelectionEventArgs(SelectionStartedEvent, selection) { Source = this };
            AssociatedObject.RaiseEvent(args);
        }

        internal void RaiseSelectionChangedEvent(Selection selection)
        {
            var args = new SelectionEventArgs(SelectionChangedEvent, selection) { Source = this };
            AssociatedObject.RaiseEvent(args);
        }

        internal void RaiseSelectionCancelledEvent(Selection selection)
        {
            var args = new SelectionEventArgs(SelectionCancelledEvent, selection) { Source = this };
            AssociatedObject.RaiseEvent(args);
        }

        internal void RaiseSelectionFinishedEvent(Selection selection)
        {
            var args = new SelectionEventArgs(SelectionFinishedEvent, selection) { Source = this };
            AssociatedObject.RaiseEvent(args);
        }

        #endregion

        #region overrides

        protected override void OnAttached()
        {
            base.OnAttached();

            OnAttachedImpl();
        }

        protected override void OnDetaching()
        {
            OnDetachingImpl();

            base.OnDetaching();
        }

        #endregion

        #region private methods

        private void OnAttachedImpl()
        {

        }

        private void OnDetachingImpl()
        {

        }

        #endregion
    }
}
